<?php
/**
 * Created by PhpStorm.
 * User: 技术员专用
 * Date: 2019/2/27
 * Time: 10:12
 */

namespace app\admin\controller;
use app\admin\controller\Welogin;
class Process 
{
    const PROCESS_NAME_LOG = ' php: swoole-bot'; //shell脚本管理标示
    const PID_FILE         = 'master.pid';
    private $reserveProcess;
    private $workers;
    private $workNum = 1;
    private $config  = [];
    public function _initialize($server, $worker_id)
    {
        // TODO: Implement _initialize() method.
    }
    public function run()
    {
        // TODO: Implement run() method.
        $ppid     = getmypid();
        print_r($ppid);
    }
    public function start(){
        \Swoole\Process::daemon(true, true);
        //设置主进程
        $ppid     = getmypid();
        $pid_file = '/www/wwwroot/tp51/public/master.pid';
        if (file_exists($pid_file)) {
            $pid=file_get_contents($pid_file);
            if ($pid) {
                //尝试三次确定是否进程还存在，存在就退出
                for ($i=0; $i < 3; ++$i) {
                    if (@\Swoole\Process::kill($pid, 0)) {
                        die('已有进程运行中,请先结束或重启' . PHP_EOL);
                    }
                    sleep(1);
                }
            }
        }
        file_put_contents($pid_file, $ppid);
        $this->setProcessName('job master ' . $ppid . self::PROCESS_NAME_LOG);

        //根据配置信息，开启多个进程
        for ($i = 0; $i < 1; ++$i) {
            $this->reserveBot($i);
            sleep(2);
        }
        $this->registSignal($this->workers);
    }

    //独立进程
    public function reserveBot($workNum)
    {
        $self           = $this;
        $reserveProcess = new \Swoole\Process(function () use ($self, $workNum) {
            //设置进程名字
            $this->setProcessName('job ' . $workNum . self::PROCESS_NAME_LOG);
            try {
                $self->config['session']='swoole-bot' . $workNum;
                echo "--------------------------";
                $job=new Welogin();
                $job->index();
            } catch (Exception $e) {
                echo $e->getMessage();
            }

            echo 'reserve process ' . $workNum . ' is working ...' . PHP_EOL;
        });
        $pid                 = $reserveProcess->start();
        $this->workers[$pid] = $reserveProcess;
        echo 'reserve start...' . PHP_EOL;
    }

    private function setProcessName($name)
    {
        //mac os不支持进程重命名
        if (function_exists('swoole_set_process_name') && PHP_OS !== 'Darwin') {
            swoole_set_process_name($name);
        }
    }

    //监控子进程
    public function registSignal(&$workers)
    {
        \Swoole\Process::signal(SIGTERM, function ($signo) {
            $this->setExit();
        });
        \Swoole\Process::signal(SIGCHLD, function ($signo) use (&$workers) {
            while (true) {
                $ret = \Swoole\Process::wait(false);
                if ($ret) {
                    $pid           = $ret['pid'];
                    $child_process = $workers[$pid];
                    //unset($workers[$pid]);
                    echo "Worker Exit, kill_signal={$ret['signal']} PID=" . $pid . PHP_EOL;
                    $new_pid           = $child_process->start();
                    $workers[$new_pid] = $child_process;
                    unset($workers[$pid]);
                } else {
                    break;
                }
            }
        });
    }

    private function setExit()
    {
        @unlink('/www/wwwroot/tp51/public/master.pid');
//        $this->logger->log('Time: ' . microtime(true) . '主进程退出' . '' . PHP_EOL);
        echo 'Time: ' . microtime(true) . '主进程退出' . '' . PHP_EOL;
        foreach ($this->workers as $pid => $worker) {
            //平滑退出，用exit；强制退出用kill
            \Swoole\Process::kill($pid);
            unset($this->workers[$pid]);
//            $this->logger->log('主进程收到退出信号,[' . $pid . ']子进程跟着退出');
//            $this->logger->log('Worker count: ' . count($this->workers));
            echo '主进程收到退出信号,[' . $pid . ']子进程跟着退出'. PHP_EOL;
            echo 'Worker count: ' . count($this->workers). PHP_EOL;
        }
        exit();
    }
}